﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once

#include <iosfwd>
#include "IGeometry.h"
#include "WeakReferenceable.h"

namespace gcmp
{
    class IVertex;
    class IEdge;
    class IFace;
    class IPoint3d;

    /// \brief 体的Brep类型
    enum class BrepType : int32_t
    {
        Unknown = -1, ///< 未知
        Solid = 0,    ///< 实体
        Sheet = 1,    ///< 薄壳体
        Wire = 2,     ///< 线框体
        Acorn = 4     ///<单点体
    };

    /// \brief 体
    ///
    class IBody : public IGeometry, public WeakReferenceable
    {
    public:
        /// \brief   获取拓扑面的数量
        /// \return  拓扑面的数量
        virtual int GetFaceCount()const = 0;

        /// \brief   获取拓扑边的数量
        /// \return  拓扑边的数量
        virtual int GetEdgeCount()const = 0;

        /// \brief   获取拓扑点的数量
        /// 加载几何库时实现开启拓扑点生成，默认BrepBody没有拓扑点，开启拓扑点生成之后这个接口才有效
        /// 如果gbmp_gcmp_behavior_config默认配置的EnableVertexGeneration不为0，开启拓扑点生成
        /// \return  拓扑点的数量
        virtual int GetVertexCount()const = 0;

        /// \brief  获取对应索引的拓扑面
        /// \param index    面的索引
        /// \return  拓扑面
        virtual const IFace* GetFace(int index)const = 0;

        /// \brief  获取对应索引的拓扑面
        /// \param index    面的索引
        /// \return  拓扑面
        virtual IFace* GetFaceFW(int index) = 0;

        /// \brief  获取对应索引的拓扑边
        /// \param index    边的索引
        /// \return  拓扑边
        virtual const IEdge* GetEdge(int index)const = 0;

        /// \brief  获取对应索引的拓扑点
        /// 加载几何库时实现开启拓扑点生成，默认BrepBody没有拓扑点，开启拓扑点生成之后这个接口才有效
        /// 如果gbmp_gcmp_behavior_config默认配置的EnableVertexGeneration不为0，开启拓扑点生成
        /// \param index    点的索引
        /// \return  拓扑点
        virtual const IVertex* GetVertex(int index)const = 0;

        /// \brief  判断是否是壳
        /// \return  是返回True，不是返回False
        virtual bool IsSheetBody() const = 0;

        /// \brief  判断是否合法
        ///
        /// \return  是返回True，不是返回False
        virtual bool IsValid() const = 0;

        /// \brief  判断边、面是否重合
        ///  针对体中的边和边、面和面进行判断, 
        /// 如果形体存在自由曲面，这个接口可能有性能问题
        /// \return  是返回True，不是返回False
        virtual bool IsEdgeFaceCoincidence() const = 0;

        /// \@brief  合并另一个体，要求合并和被合并的体都是ggp的BrepBody;
        /// \param[in] IBody* anotherBody 被合并的体
        /// \return    void
        virtual void MergeBody(IBody* anotherBody) = 0;

        /// \brief  如果m_opBody成员是 CBrepBody类型的，则判断其中facelist中是否含有空的surface指针
        /// \return True：检测到了null surface指针；False：没有检测到null surface指针
        virtual bool HasNullSurfacePtr() const = 0;

        /// \brief 获取体的面积
        ///
        /// \return 返回面积
        virtual double GetArea() const = 0;

        /// \brief 获取体的体积
        ///
        /// \return 返回体积
        virtual double GetVolume() const = 0;

        /// \brief 获取体的容差
        ///
        /// \return 返回容差
        virtual double GetDistEpsilon() const = 0;

        /// \brief 获取体的几何点
        /// \param[out] points 几何点数组
        /// \return 成功返回true,否则返回false
        virtual bool GetPoints(std::vector<OwnerPtr<IPoint3d>>& points) const = 0;

        /// \brief 获取体的Brep类型
        ///
        /// \return 返回体的Brep类型
        virtual BrepType GetBrepType() const = 0;

        /// \brief 设置体的Brep类型
        ///
        /// 只支持实体转成壳体，或者封闭的壳体转成实体，其他会返回false
        /// \param type 体的类型
        /// \return 成功返回true,否则返回false
        virtual bool SetBrepType(BrepType type) = 0;

        /// \brief 获取实体的重心坐标（仅支持Solid实体）
        /// \param[out] barycenterPt 实体的重心坐标
        /// \return 成功返回true,否则返回false
        virtual bool GetBarycentre(Vector3d& barycenterPt) const = 0;

        /// \brief  判断体是否为空
        /// \return true: 为空，false: 不为空
        virtual bool IsEmpty() const = 0;

        /// \brief  判断Wire Body是否封闭
        /// \return true: 首尾相连且封闭，  false: 不封闭或边首尾不相连，或者不是WireBody
        virtual bool IsClosedWire() const = 0;

        /// \brief  判断反向指定边
        /// \param[in] edgeIndex 被反向边的索引，如果为-1，则对所以边进行操作
        /// \return    void
        virtual void ReverseEdge(int edgeIndex) = 0;
    public:
        virtual ~IBody() {}
    };
}
